home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / comm / net / amipop112.lha / AmiPOP112 / source / pop_dopop.c < prev    next >
C/C++ Source or Header  |  1994-08-09  |  9KB  |  579 lines

  1. #include "pop.h"
  2.  
  3. /* Stuff for "From " Header */
  4. /* Courtesy Michael B. Smith */
  5.  
  6.  
  7. struct mytm    {
  8.                 int year;
  9.                 int month;
  10.                 int day;
  11.                 int dow;
  12.                 int hour;
  13.                 int min;
  14.                 int sec;
  15.             };
  16.  
  17. /* DaysInMonth */
  18. static const int    dim [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  19. static const char    *months [] = {    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  20.                                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  21. static const char    *days [] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  22.  
  23. static void DateStampToMyTm (struct DateStamp *date, struct mytm *da)
  24. {
  25.     int days, years, leap  = 0, month = 0;
  26.  
  27.     days = date->ds_Days + 731;        /*  1976    */
  28.     years = days / (365*3+366);        /*  #quad yrs    */
  29.     days -= years * (365*3+366);
  30.     years = 1976 + 4 * years;
  31.  
  32.     if (days <= 365)
  33.     {
  34.         leap = 1;
  35.     }
  36.     else
  37.     {
  38.         days -= 366;
  39.         ++years;
  40.         years += days / 365;
  41.         days %= 365;
  42.     }
  43.  
  44.     month = 0;
  45.     while (1)
  46.     {
  47.         if (month == 1)
  48.         {
  49.             if (days < (28 + leap)) break;
  50.             days -= 28 + leap;
  51.         }
  52.         else
  53.         {
  54.             if (days < dim [month]) break;
  55.             days -= dim [month];
  56.         }
  57.         ++month;
  58.     }
  59.  
  60.     da->hour   = date->ds_Minute / 60;
  61.     da->min    = date->ds_Minute % 60;
  62.     da->sec    = date->ds_Tick / 50;
  63.  
  64.     da->day    = days + 1;
  65.     da->month  = month + 1;
  66.     da->dow    = date->ds_Days % 7;    /*  0 = sunday   */
  67.     da->year   = years;
  68.  
  69.     return;
  70. }
  71.  
  72. char * datestr (char *buf)
  73. {
  74.     /*
  75.     **  datestr
  76.     **
  77.     **    Build ARPA date-time as specified in RFC-822:
  78.     **
  79.     **        Wed, 13 Oct 93 18:52:04 EST
  80.     **        123456789012345678901234567890
  81.     **
  82.     **    buf must be 24 characters, plus space for TimeZone and NUL.
  83.     **
  84.     **    As TimeZone may be "(+23:30)" or similar, 33 chars should
  85.     **    do it.
  86.     */
  87.     struct mytm da;
  88.     struct DateStamp ds;
  89.  
  90.     DateStampToMyTm (DateStamp (&ds), &da);
  91.  
  92.     DoFmt (buf, "%s, %ld %s %ld %02ld:%02ld:%02ld",
  93.                 days [da.dow], da.day,
  94.                 months [da.month - 1], da.year % 100,
  95.                 da.hour, da.min, da.sec);
  96.  
  97.     return buf;
  98. }
  99.  
  100. char * time_stamp (char *buf)
  101. {
  102.     /*
  103.     **  time_stamp
  104.     **
  105.     **    Put a time/date stamp into buf (for logging)
  106.     **
  107.     **    13 Nov 93 13:14:45
  108.     */
  109.     struct DateStamp ds;
  110.     struct mytm da;
  111.  
  112.     DateStampToMyTm (DateStamp (&ds), &da);
  113.  
  114.     DoFmt (buf, "%ld %s %ld %02ld:%02ld:%02ld",
  115.                 da.day,
  116.                 months [da.month - 1], da.year % 100,
  117.                 da.hour, da.min, da.sec);
  118.  
  119.     return buf;
  120. }
  121.  
  122. /*  End stuff for "From " header */
  123.  
  124.  
  125. #define ASYNCBUFSIZE 8192
  126.  
  127. BOOL needfrom ( char * , struct AsyncFile *);
  128.  
  129. /* Variables global to this file */
  130.  
  131. struct Library *SockBase ;
  132. int havemail;
  133.  
  134. /* Functions */
  135.  
  136. int dopop(void)
  137. {
  138.     int s;
  139.     int count;
  140.     int okay=1;
  141.     struct hostent *hp;
  142.     struct sockaddr_in sa;
  143.  
  144.     DoFmt(title,"Connecting to %s",pophost);
  145.     settitle(title);
  146.  
  147.     if((SockBase = OpenLibrary( SOCKLIBNAME, SOCKLIBVERSION )) == NULL)
  148.     {
  149.         doreq("Error opening socket.library\n",bum);
  150.         return(1);
  151.     }
  152. #ifdef AMITCP
  153.     SetErrnoPtr(&errno, sizeof errno);
  154. #else
  155.     setup_sockets( MAXSOCKS, &errno );
  156. #endif
  157.  
  158.     if((hp=gethostbyname(pophost))==NULL)
  159.     {
  160. #ifndef AMITCP
  161.         cleanup_sockets();
  162. #endif
  163.         CloseLibrary( SockBase ) ;
  164.         doreq("Connection Refused.",bum);
  165.         return(1);
  166.     }
  167.  
  168.     bzero(&sa, sizeof(sa));
  169.     bcopy(hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
  170.     sa.sin_family = hp->h_addrtype;
  171.     sa.sin_port = htons((u_short)port);
  172.     if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)
  173.     {
  174. #ifndef AMITCP
  175.         cleanup_sockets();
  176. #endif
  177.         CloseLibrary( SockBase ) ;
  178.         doreq("Something bad\nhas happened.",bum);
  179.         return(1);
  180.     }
  181.  
  182.     if (connect(s,(struct sockaddr *) &sa,sizeof(sa))< 0)
  183.     {
  184.         doreq("No POP3 daemon\nrunning on this\nmachine or port.",bum);
  185.         s_close(s);
  186. #ifndef AMITCP
  187.         cleanup_sockets();
  188. #endif
  189.         CloseLibrary( SockBase ) ;
  190.         return(1);
  191.     }
  192.  
  193. /* Put actual code here */
  194.  
  195.     recv(s,buf,BUFSIZE-1,0);
  196.     settitle("Got Connection");
  197.  
  198.     sendgreet(s);
  199.  
  200.     if (senduser(s))
  201.     {
  202. #ifndef AMITCP
  203.         cleanup_sockets();
  204. #endif
  205.         CloseLibrary( SockBase ) ;
  206.         return(1);
  207.     }
  208.  
  209.     count=havemail=sendstat(s);
  210.  
  211.     while (count && okay)
  212.     {
  213.         DoFmt(title,"Retrieving %lu",count);
  214.         settitle(title);
  215.  
  216.         okay=retrieve(s,count);
  217.  
  218.         if (delmail && okay)
  219.         {
  220.             DoFmt(title,"Deleting %lu",count);
  221.             settitle(title);
  222.  
  223.             okay=delmessage(s,count);
  224.         }
  225.         --count;
  226.     }
  227.  
  228.     if(sendquit(s))
  229.     {
  230. #ifndef AMITCP
  231.         cleanup_sockets();
  232. #endif
  233.         CloseLibrary( SockBase ) ;
  234.         return(1);
  235.     }
  236.  
  237.     if (Project0Wnd)
  238.     {
  239.         SetWindowTitles(Project0Wnd,Project0Wdt, (UBYTE *) ~0);
  240.     }
  241.  
  242.     if (havemail && notify) /* removed sendstat() after Nofify */
  243.     {
  244.         doreq("You have new mail.","Cool");
  245.     }
  246.  
  247. /* End actual code */
  248.  
  249.     s_close(s);
  250. #ifndef AMITCP
  251.     cleanup_sockets();
  252. #endif
  253.     CloseLibrary( SockBase ) ;
  254.     return(0);
  255. }
  256.  
  257. int sendgreet(int s)
  258. {
  259.     DoFmt(buf,"HELLO\r\n");
  260.     trans(s,buf);
  261.  
  262.     return(0);
  263. }
  264.  
  265. int senduser(int s)
  266. {
  267.     int t;
  268.  
  269.     settitle("Sending Username");
  270.  
  271.     DoFmt(buf,"USER %s\r\n",username);
  272.  
  273.     if ( !trans(s,buf) ) return(1);
  274.  
  275.     t=sscanf(buf,"%s",temp);
  276.     if ( valcheck(t,temp) ) return(1);
  277.  
  278. /* Password */
  279.  
  280.     settitle("Sending Password");
  281.  
  282.     DoFmt(buf,"PASS %s\r\n",password);
  283.  
  284.     if ( !trans(s,buf) ) return(1);
  285.  
  286.     t=sscanf(buf,"%s",temp);
  287.  
  288.     if ( valcheck(t,temp) ) return(1);
  289.  
  290.     return(0);
  291. }
  292.  
  293. int sendquit(int s)
  294. {
  295.     int t;
  296.  
  297.     settitle("Sending QUIT");
  298.  
  299.     DoFmt(buf,"QUIT\r\n");
  300.  
  301.     if ( !trans(s,buf) ) return(1);
  302.  
  303.     t=sscanf(buf,"%s",temp);
  304.  
  305.     if ( valcheck(t,temp) ) return(1);
  306.  
  307.     settitle("Quit Acknowledged");
  308.  
  309.     return(0);
  310. }
  311.  
  312. int sendstat( int s )
  313. {
  314.     int t;
  315.     int count=0;
  316.  
  317.     DoFmt(buf,"STAT\r\n");
  318.  
  319.     if ( !trans(s,buf) ) return(0);
  320.  
  321.     t=sscanf(buf,"%s %lu",temp,&count);
  322.  
  323.     if ( valcheck(t,temp) ) return(0);
  324.  
  325.     return(count);
  326. }
  327.  
  328. int retrieve(int s,int count)
  329. {
  330.     int foo;
  331.     int c;
  332.     int goon=1;
  333.  
  334.     char *havefrom;
  335.     char *buf2;
  336.     char *buf3;
  337.  
  338.     BOOL begin=TRUE;
  339.     struct AsyncFile *ofp;
  340.  
  341.     if (havefrom=AllocVec(512,MEMF_CLEAR))
  342.     {
  343.         if ( (count == havemail) && (!appfile) )
  344.         {
  345.             ofp = OpenAsync(maildir, MODE_WRITE,ASYNCBUFSIZE);
  346.         }
  347.         else
  348.         {
  349.             ofp = OpenAsync(maildir, MODE_APPEND,ASYNCBUFSIZE);
  350.         }
  351.  
  352.         if ( ofp == NULL)
  353.         {
  354.             doreq("Open() failed\n",bum);
  355.             FreeVec(havefrom);
  356.             return(0);
  357.         }
  358.  
  359.         DoFmt(buf,"RETR %lu\r\n",count);
  360.  
  361.         if ( !trans(s,buf) )
  362.         {
  363.             CloseAsync(ofp);
  364.             FreeVec(havefrom);
  365.             return(0);
  366.         }
  367.  
  368.         if ( valcheck(1,buf) )
  369.         {
  370.             CloseAsync(ofp);
  371.             FreeVec(havefrom);
  372.             return(0);
  373.         }
  374.  
  375.         buf3=strstr(buf,"\r\n");
  376.  
  377.         if ( (buf3) && (buf3+2) )
  378.         {
  379.             char *buf4;
  380.  
  381.             if (needfrom(buf3,ofp))
  382.             {
  383.                 begin=FALSE;
  384.             }
  385.  
  386.             buf4=strip(buf3);
  387.             buf3=stpchrn(buf4,0x20);
  388.             if (buf3)
  389.             {
  390.                 WriteAsync(ofp,buf3,strlen(buf3));
  391.             }
  392.         }
  393.  
  394.         while ( goon )
  395.         {
  396.             foo=recv(s,buf,BUFSIZE-1,0);
  397.  
  398.             if (foo < 1)
  399.             {
  400.                 goon=0;
  401.             }
  402.  
  403.             buf[foo]='\0';
  404.  
  405.             goon=lastblock(buf);
  406.  
  407.             /* Magic to add "From " header */
  408.  
  409.             if (begin && goon)
  410.             {
  411.                 needfrom(buf,ofp);
  412.             }
  413.  
  414.             begin=FALSE;
  415.  
  416.             buf2=strip(buf);
  417.  
  418.             c=WriteAsync(ofp,buf2,strlen(buf2));
  419.  
  420.             if (c == -1)
  421.             {
  422.                 doreq("FPuts() failed!",bum);
  423.                 goon=0;
  424.             }
  425.         }
  426.  
  427.         WriteAsync(ofp,"\n",1);
  428.         CloseAsync(ofp);
  429.  
  430.         FreeVec(havefrom);
  431.         return(1);
  432.     }
  433.     else
  434.     {
  435.         return(0);
  436.     }
  437.  
  438. }
  439.  
  440. int delmessage( int s, int count )
  441. {
  442.     DoFmt(buf,"DELE %lu\r\n",count);
  443.     trans(s,buf);
  444.  
  445.     if ( valcheck(1,buf) ) return(0);
  446.  
  447.     return(1);
  448. }
  449.  
  450. int valcheck(int t, char *localtemp)
  451. {
  452.     if (t == 0)
  453.     {
  454.         doreq("scanf() failed\n",bum);
  455.         return(1);
  456.     }
  457.  
  458.     if ( !strstr(localtemp,"+OK") )
  459.     {
  460.         doreq("Didn't get +OK",bum);
  461.  
  462.         if (localtemp[0] != '\0')
  463.         {
  464.             doreq(localtemp,bum);
  465.         }
  466.         return(1);
  467.     }
  468.     return(0);
  469. }
  470.  
  471. int trans( int s, char *mybuf )
  472. {
  473.     int foo;
  474.  
  475.     send(s,mybuf,strlen(mybuf),0);
  476.  
  477.     foo=recv(s,buf,BUFSIZE-1,0);
  478.  
  479.     if ( foo < 1 )
  480.     {
  481.         return(0);
  482.     }
  483.  
  484.     buf[foo]='\0';
  485.  
  486.     return (1);
  487. }
  488.  
  489. void settitle( char *newtitle )
  490. {
  491.     if (winop)
  492.     {
  493.         SetWindowTitles(Project0Wnd,newtitle, (UBYTE *) ~0);
  494.     }
  495. }
  496.  
  497. char *strip( char *mybuf )
  498. {
  499.     char out[BUFSIZE]="";
  500.     ULONG x1=0;
  501.     ULONG x2=0;
  502.     ULONG len;
  503.  
  504.     len=strlen(mybuf);
  505.  
  506.     while (mybuf[x1] != '\0' )
  507.     {
  508.         while (mybuf[x1] == '\r')
  509.         {
  510.             ++x1;
  511.         }
  512.         out[x2]=mybuf[x1];
  513.         ++x2;
  514.         if (x1 < len)
  515.         {
  516.             ++x1;
  517.         }
  518.     }
  519.     out[x2]='\0';
  520.  
  521.     strcpy(mybuf,out);
  522.  
  523.     return(mybuf);
  524. }
  525.  
  526. int lastblock (char *segment)
  527. {
  528.     char *found;
  529.     int len = strlen(segment);
  530.  
  531.     if ( (found=strstr(segment,"\r\n.\r\n")))
  532.     {
  533.         /*buf[found-segment]='\n';*/
  534.         buf[found-segment]='\0'; /* used to be found-segment+2 */
  535.         return(0);
  536.     }
  537.  
  538.     if ( (len==2) && (found=strstr(segment,"\r\n")) )
  539.     {
  540.         buf[found-segment]='\0'; /* Added recently */
  541.         return(0);
  542.     }
  543.  
  544.     if ( len==1 ) /* Kludge of the century */
  545.     {
  546.         return(0);
  547.     }
  548.  
  549.     if ( (len <= 4) && (found=strstr(segment,".\r\n")) )
  550.     {
  551.         /*buf[found-segment]='\n';*/
  552.         buf[found-segment]='\0';
  553.         return(0);
  554.     }
  555.  
  556.     return(1);
  557. }
  558.  
  559. BOOL needfrom(char *mybuf,struct AsyncFile *ofp)
  560. {
  561.     if ( !strstr(mybuf,"From ") )
  562.     {
  563.         char *newtemp;
  564.  
  565.         if (newtemp=AllocVec(BIGSTRING,MEMF_CLEAR))
  566.         {
  567.             int tempsize=0;
  568.  
  569.             DoFmt(newtemp,"From %s@%s ", username,pophost);
  570.             tempsize=strlen(newtemp);
  571.             DoFmt((newtemp+tempsize),"%s\n",datestr((newtemp+tempsize)));
  572.             WriteAsync(ofp,newtemp,strlen(newtemp));
  573.             FreeVec(newtemp);
  574.         }
  575.  
  576.         return(TRUE);
  577.     }
  578.     return(FALSE);
  579. }